
// 用Nodejs的express搭建http服务器：
var express = require('express')
var serve_index = require('serve-index');

var bodyParser = require('body-parser');
const url = require('url');

//支持 'Content-Type': 'multipart/form-data;
var multiparty = require('multiparty');

//文件
var fs = require('fs');

var mysql = require('mysql');

var path  = require('path');


// https://blog.csdn.net/qq_39905409/article/details/87905335
var expressJwt = require('express-jwt');
var vertoken = require('./token_vertify.js');

var loginRouter = require('./logIn.js');

//设置端口
var port = 8092;
var app = express();

let Login = require('./logIn2.js');

/*
* session
* cookie
* token
* */

//Nodejs req.body 默认为空。如果使用了 express 框架，可以输入以下代码解决
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());

var routes = express.Router();

// app.use("/req", routes);

// 发布静态目录，静态目录是当前路径下的public文件夹
// serve-index是一个NodeJS模块，功能是将文件夹中文件列表显示到浏览器中，可以通过NPM安装。
// app.use(serve_index('./public', {'icons': true}));

app.use(express.static('./public'));
// app.use('/static',express.static('./public'));

//不输入hostname参数，访问的url，任意url均可访问
var server = app.listen(port, (err) => {
    if (err) {
        console.log(err);
    } else {
        console.log(`服务开启成功【端口号:${port}】`);
    }
});

//网页打开根目录(http://127.0.0.1:8892),默认是  app.use(express.static('./public')); 下面的index.html
// app.get('/',function (req,res) {
//
//     res.render('index');
//     // res.redirect('./H5OnLine/testhttp.html');
// })

/**
 * express建立GET接口
 * http://192.168.1.7:8092/req/login?name='name12'&pwd='123'
 * */



// app.get('/index.html',function (req,res) {
//
//     // res.render('index.html');
//     res.sendFile( __dirname + "/index.html" );
//     res.end();
// })

/*
* nodejs 自动生成文档
* https://www.jianshu.com/p/7e1b057b047c/

https://blog.csdn.net/weixin_44420276/article/details/104259586?utm_medium=distribute.pc_relevant_t0.none-task-blog-searchFromBaidu-1.control&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-searchFromBaidu-1.control
* */

// error handler
app.use(function (err, req, res, next) {
    console.log(err);
    if (err.name === 'UnauthorizedError') {
        console.error(req.path + ',无效token');
        res.json({
            message: 'token过期，请重新登录',
            code: 400
        })
        return
    }
    // render the error page
    res.status(err.status || 500);
    res.render('error');
});

//所有请求拦截,代码写在所有接口之前，否则拦截不到
app.use(function (req,res,next) {

    //设置允许跨域
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "X-Requested-With,Content-Type");
    res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");

    //这段仅仅为了方便返回json而已
    // res.header("Content-Type", "application/json;charset=utf-8");
    // if(req.method == 'OPTIONS') {
    //     //让options请求快速返回
    //     res.sendStatus(200);
    // } else {
    //     next();
    // }
//拦截是否登录等
    console.log('拦截'+req.path);
    // next();

    if ( req.path === '/api/log/login' )
    {
        console.log("login");
        next();
    }
    else
    {
        //TODO:验证token有效性
        console.log("验证token有效性");
        var token = req.headers['authorization'];

        if(!token){
            console.log("未获取到token");

            return res.json({status:301,des:"unlogin"});
            // return next();
        }else{
            console.log("token="+token);
            vertoken.verToken(token).then((data)=> {

                //用户信息赋值到请求信息里面，具体业务根据用户信息来对应操作
                req.data = data;
                //验证成功后，判断是那个用户
                console.log("token验证 账号:"+data.name);
                return next();
            }).catch((error)=>{
                console.log("token验证异常"+error);
                // return next(error);
                return res.json({status:301,des:"unlogin"});
            })
        }
    }
})



//验证token是否过期并规定哪些路由不用验证
//请求时 为 Bearer token形式，具体可以在headers里面添加 authorization 值为登录时返回的token
// ，同时需要在返回的token前面添加 "Bearer "
//如返回的 为 token:xxxxxx123 那么请求的headers里面 为 authorization:Bearer xxxxxx123
//JWT 是数字签名，所以只需要 public key 和受信任的时间即可验证有效性,所有服务器重启后，仍然有效，不需要存储，所以如果用户退出登录，其实之前的token仍然有效
//安全性不高，登录生成token时 加个随机数相对安全一些，后面主要靠有效期，或者业务层加保护
//jwt是一次签发永久有效。所以登录多次token变了，多个token值都可以使用，如果想登录一次，之前token失效，那么需要应用层来控制
//下面代码会自动验证所有请求，上面的是手动验证token,手动更灵活
// app.use(expressJwt({
//     secret: 'mes_qdhd_mobile_xhykjyxgs',algorithms:['sha1', 'RS256', 'HS256'],
// }).unless({
//     path: ['/api/log/login']//除了这个地址，其他的URL都需要验证
// }));


// Login(app);

//分文件写接口
app.use('/api/log',loginRouter);

app.get('/login2', (req, res) => {
    var string = url.parse(req.url, true);
    //解析参数
    var params = url.parse(req.url, true).query;
    console.log(params);
    console.log("req.data.name:" + req.data.name);
    var user = {};
    user.name = params.name;
    user.pwd = params.pwd;
    var responseJson = { name: 'abc', pwd: '123' };
    var response = { status: 3, data: user };
    // res.send(JSON.stringify(response));
    console.log("URL:" + req.url + "  " + string.pathname);
    res.status(200).json(response);
    //有数据返回用res.send();
    //无数据返回用res.end();
    // res.end("hello nodejs");

    //情况控制台日志
});


//express错误处理  404 自定义，代码写在所有接口定义之后，否则不存在的url不会调用下面的方法
app.get('*',function (req,res) {
    // res.send('my custom 404 not found',404);
    // res.status(404).json({"err":"404"});

    console.log(req.url + " 404");
    res.status(404).send('Sorry, we cannot find that!');
    res.end();


    //读取指定文件返回
    // var form = fs.readFileSync('./public/H5OnLine/h5Device.html', { encoding: 'utf8' });
    // res.send(form);

    // console.log("***:" + req.url);

    //404重定向到指定页面
    // res.redirect('./H5OnLine/testhttp.html');
    // res.redirect(302,'http://www.baidu.com');
});



/**
 * token
 * https://www.jianshu.com/p/663520bd7e95
 * https://my.oschina.net/u/4417891/blog/3684252
 * */
/**
nodejs服务器项目目录结构
https://github.com/jifeng/node-app
* */


/**
 * express建立POST接口
 */
routes.post('/r', (req, res) => {
    var string = url.parse(req.url, true);
    console.log("URL:" + req.url + "  " + string.pathname);
    //解析参数
    var params = req.body;
    console.log("params:"  + params);

    var user = {};
    user.name = params.name;
    user.pwd = params.pwd;
    var response = { status: 1, data: user };
    res.send(JSON.stringify(response));
    // res.send('post:' + string.pathname + "  " +
    //     JSON.stringify(text));
    res.end();
    console.log(req.method);//post
    console.log(req.body);//{ a: '3', b: '4', c: '5' }
    // console.log(req.body.a); //3
    // res.end("hello nodejs");
});

function isJson (obj){
    var isjson = typeof(obj) == "object" && Object.prototype.toString.call(obj).toLowerCase() == "[object   object]" && !obj.length;
    return isjson;
}

//路径最后需要加 "/"
//自动创建多层目录
function mkdir(filepath) {
    const arr=filepath.split('/');
    const dirCache={};

    console.log("filePath",filepath);

    let dir=arr[0];
    for(let i=1;i<arr.length;i++){
        if(!dirCache[dir]&&!fs.existsSync(dir)){
            dirCache[dir]=true;
            fs.mkdirSync(dir);
        }
        dir=dir+'/'+arr[i];
    }
}

 //表单形式上传文件
routes.post('/upImg', (req, res) => {

    console.log("body " + req.body);

    //生成multiparty对象，并配置上传目标路径
    var form = new multiparty.Form();

    //路径不存在，则需要提前创建
    // form.uploadDir = './public/images2/subImg/';
    form.uploadDir = './public/images/';
    // form.partFilename = '1.jpg';
    // form.partName

//检查某个目录是否存在
    //异步，需要加个promise，实现同步形式
    fs.exists(form.uploadDir, function (exists) {

        console.log(exists ? "路径存在" : "路径不存在");
        if (!exists) {
        }
        mkdir(form.uploadDir);
    })

    //单文件大小限制
    form.maxFieldsSize = 1024*1024 * 5;

    //一次上传文件数量
    //form.maxFields = 1000;  设置所以文件的大小总和

    form.parse(req, function(err, fields, files) {
        // console.log(fields, files,' fields2');

        if (err)
        {
            console.log("upImg para err" + err);
            res.json({status:201});
            return;
        }

        //自定义参数
        console.log("fields");
        console.log(fields);
        console.log("files");
        console.log(files);
        // console.log(fields.user[0]);

        // let userInfo = fields.user[0];

        // if (isJs

        //文件参数
        // console.log(files);
        // console.log(files.file[0].path);

        // files.file[0].path = './public/images/123on(userInfo))
        //         // {
        //         //     console.log('userinfo is json');
        //         // }
        //         // console.log(userInfo.type);.jpg';

        //同步重命名文件名
        // fs.rename(files.file[0].path, './public/images2/456.jpg', function (err) {
        //
        //     if (err) {
        //         console.log(err);
        //         console.log("修改文件名称失败");
        //     }
        // });

        if (err) {
        } else {
            // res.json({ imgSrc: files.image[0].path })
        }
        res.json({status:200});
        res.end();
    });
});
